package javango.db;

public abstract class AbstractPaginator<T> implements Paginator<T> {

	Integer numPages = null;
	boolean allowEmptyFirstPage = true;
	
	protected final int perPage;
	protected final int orphans;

	/**
	 * Create a new AbstractPaginator with orphans set to 5
	 * 
	 * @param perPage
	 */
	public AbstractPaginator(int perPage) {
		this(perPage, 5);
	}

	public AbstractPaginator(int perPage, int orphans) {
		this.perPage = perPage;
		this.orphans = orphans;
	}
	
	/**
	 * Validates the given 1-based page number.  should be used by getPage to validate that the requested page is ok.
	 * @param number
	 * @return
	 */
	protected int validateNumber(int number) {
		if (number < 1) {
			throw new IllegalArgumentException("That page number is less than 1"); 
		} else if ( number > this.getNumPages() ) {
			if (number == 1 && this.allowEmptyFirstPage ) {
			} else {
				throw new IllegalArgumentException("That page contains no results");
			}
		}
		return number;
	}

	public int getNumPages() {
		if (this.numPages == null) {
	    	 if ((this.getCount() == 0) && (!this.allowEmptyFirstPage))  {
		    	 this.numPages = 0;
	    	 } else {
	    		 int hits = Math.max(1, this.getCount() - this.getOrphans());
				 this.numPages = (int)Math.ceil((float)hits / (float)this.perPage);
	    	 }
		}
		return this.numPages;
	}

	public String toString() {
		StringBuilder b = new StringBuilder();
		b.append("paginate_by: " );
		b.append(perPage);
		b.append("; pages: ");
		b.append(getNumPages());
		b.append("; hits: ");
		b.append(getCount());
		return b.toString();
	}

	public int getPerPage() {
		return perPage;
	}

	public int getOrphans() {
		return orphans;
	}

}